home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / (A)Z / (A)Z8.ADF / Muncho / audio.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  10KB  |  419 lines

  1. #include <lattice/stdio.h>
  2. #include <exec/types.h>
  3. #include <devices/audio.h>
  4. #include <devices/timer.h>
  5.  
  6. #define TICKS_PER_SEC        (3579545.0)
  7. #define PRIORITY             (100)
  8. #define SOUND_PRIORITY         (50)
  9. #define MAXBUF                  (131000)
  10.  
  11. extern struct MsgPort *CreatePort();
  12. extern struct IOAudio *GetMsg();
  13.  
  14.  
  15.  int timOpened;
  16.  int finOpened;
  17.  
  18.  UBYTE allocMap[] = {1,2,4,8};
  19.  int inUse[] = {0,0,0,0};
  20.  
  21.  struct MsgPort *port5_ = NULL;
  22.  struct MsgPort *port6_ = NULL;
  23.  struct MsgPort *port7_ = NULL;
  24.  struct MsgPort *port8_ = NULL;
  25.  struct MsgPort *port9_ = NULL;
  26.  struct MsgPort *port10_ = NULL;
  27.  struct MsgPort *port11_ = NULL;
  28.  
  29.  struct IOAudio     sIO1;
  30.  struct IOAudio     sIO2;
  31.  struct IOAudio     sIO3;
  32.  struct IOAudio     sIO4;
  33.  
  34.  struct IOAudio     finishIO;
  35.  struct IOAudio     ctlIO;
  36.  struct IOAudio     flushIO;
  37.  
  38.  struct IOAudio      *sIOarray_[4];
  39.  
  40.  struct timerequest timReq;
  41.  long          timMsg;
  42.  struct MsgPort      *timPort_ = NULL;
  43.  
  44.  int nextTry;
  45.  
  46.  static int doneInit = 0;
  47.  
  48.  
  49.  
  50. /*
  51. ---------------------------------------------------------------------------
  52.             audio_init
  53. ---------------------------------------------------------------------------
  54.     Initializes the audio device.
  55.     Receives:
  56.      <nothing>
  57.     Returns:
  58.      int status    -completion status
  59.               0 ==> OK
  60. ===========================================================================
  61. */
  62. audio_init()
  63. {
  64.  
  65.    doneInit = 1;
  66. /*
  67. Open the audio device:
  68. ======================*/
  69.    if(!(port5_=CreatePort("s5",0))){
  70.       return(2);
  71.    }
  72.    if(!(port6_=CreatePort("s6",0))){
  73.       return(2);
  74.    }
  75.    if(!(port7_=CreatePort("s7",0))){
  76.       return(2);
  77.    }
  78.    if(!(port8_=CreatePort("s8",0))){
  79.       return(2);
  80.    }
  81.    if(!(port9_=CreatePort("ctrl2",0))){
  82.       return(3);
  83.    }
  84.    if(!(port10_ = CreatePort("ctrl3",0))){
  85.       return(3);
  86.    }
  87.    if(!(port11_ = CreatePort("ctrl4",0))){
  88.       return(3);
  89.    }
  90.    if(OpenDevice(AUDIONAME,0,&finishIO,0)){
  91.       finOpened = 0;
  92.       return(4);
  93.    }
  94.    finOpened = 1;
  95. /*
  96. Initialize the audio request blocks:
  97. ====================================*/
  98.    sIO1 = finishIO;
  99.    sIO2 = finishIO;
  100.    sIO3 = finishIO;
  101.    sIO4 = finishIO;
  102.    flushIO = finishIO;
  103.    ctlIO = finishIO;
  104.    sIO1.ioa_Request.io_Message.mn_ReplyPort = port5_;
  105.    sIO2.ioa_Request.io_Message.mn_ReplyPort = port6_;
  106.    sIO3.ioa_Request.io_Message.mn_ReplyPort = port7_;
  107.    sIO4.ioa_Request.io_Message.mn_ReplyPort = port8_;
  108.    finishIO.ioa_Request.io_Message.mn_ReplyPort = port9_;
  109.    flushIO.ioa_Request.io_Message.mn_ReplyPort = port10_;
  110.    ctlIO.ioa_Request.io_Message.mn_ReplyPort = port11_;
  111.  
  112.    finishIO.ioa_Request.io_Flags = IOF_QUICK;
  113.    finishIO.ioa_Request.io_Command = ADCMD_FINISH;
  114.    finishIO.ioa_Data = NULL;
  115.    finishIO.ioa_Length = 0;
  116.    flushIO.ioa_Request.io_Flags = IOF_QUICK;
  117.    flushIO.ioa_Request.io_Command = CMD_FLUSH;
  118.    flushIO.ioa_Data = NULL;
  119.    flushIO.ioa_Length = 0;
  120.    flushIO.ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
  121.    sIO1.ioa_Request.io_Command = CMD_WRITE;
  122.    sIO1.ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK|ADIOF_SYNCCYCLE;
  123.    sIO2.ioa_Request.io_Command = CMD_WRITE;
  124.    sIO2.ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK|ADIOF_SYNCCYCLE;
  125.    sIO3.ioa_Request.io_Command = CMD_WRITE;
  126.    sIO3.ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK|ADIOF_SYNCCYCLE;
  127.    sIO4.ioa_Request.io_Command = CMD_WRITE;
  128.    sIO4.ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK|ADIOF_SYNCCYCLE;
  129.    sIOarray_[0] = &(sIO1);
  130.    sIOarray_[1] = &(sIO2);
  131.    sIOarray_[2] = &(sIO3);
  132.    sIOarray_[3] = &(sIO4);
  133. /*
  134. Open a timer:
  135. =============*/
  136.     if(!(timPort_=CreatePort(0,0))){
  137.               return(10);
  138.     }
  139.        timReq.tr_node.io_Message.mn_ReplyPort = timPort_;
  140.        if(OpenDevice(TIMERNAME,UNIT_VBLANK,&timReq,0)){
  141.         timOpened = 0;
  142.               return(11);
  143.        }
  144.     timOpened = 1;
  145.        timReq.tr_node.io_Message.mn_ReplyPort = timPort_;
  146.        timReq.tr_node.io_Command = TR_ADDREQUEST;
  147.        timReq.tr_node.io_Flags = 0;
  148.        timReq.tr_node.io_Error = 0;
  149.        timMsg = 1L << timPort_->mp_SigBit;
  150.  
  151.    nextTry = 0;
  152.    return(0);
  153. }
  154.  
  155.  
  156.  
  157. /*
  158. ---------------------------------------------------------------------------
  159.             audio_sound
  160. ---------------------------------------------------------------------------
  161.     Simulates the sound of a picked string.
  162.     Receives:
  163.      BYTE *s_    -pointer to the data for the sound
  164.      int sLen    -length of sound data in bytes
  165.      int volume    -volume (0 to 64)
  166.     Returns:
  167.      <nothing>
  168. ===========================================================================
  169. */
  170. audio_sound(s_,sLen,period,volume)
  171. BYTE *s_;
  172. ULONG sLen;
  173. int period;
  174. int volume;
  175. {
  176.     struct IOAudio *mySound_;
  177.     int ch;
  178.     int u;
  179.     int k;
  180.  
  181. /*
  182. Check if there's any IO requests that have finished:
  183. ====================================================*/
  184.     ch = GetChannel(&u,&k);
  185. /*
  186. Setup the number of repeats:
  187. ============================*/
  188.     mySound_ = sIOarray_[ch];
  189. /*
  190. Setup the sound message:
  191. ========================*/
  192.     mySound_->ioa_Data   = s_;
  193.     mySound_->ioa_Period    = period;
  194.     mySound_->ioa_Length = sLen;
  195.     mySound_->ioa_Cycles = 1;
  196.     mySound_->ioa_Volume    = volume;
  197.     mySound_->ioa_AllocKey = k;
  198.     mySound_->ioa_Request.io_Flags = ADIOF_PERVOL;
  199.     mySound_->ioa_Request.io_Unit = u;
  200.     mySound_->ioa_Request.io_Message.mn_Node.ln_Pri = SOUND_PRIORITY;
  201. /*
  202. Play the sound:
  203. ===============*/
  204.     BeginIO(mySound_);
  205.     return(0);
  206. }
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213. /*
  214. ---------------------------------------------------------------------------
  215.             audio_close
  216. ---------------------------------------------------------------------------
  217.     Closes the audio device and de-allocates all associated memory.
  218.     Receives:
  219.      <nothing>
  220.     Returns:
  221.      <nothing>
  222. ===========================================================================
  223. */
  224. audio_close()
  225. {
  226.     int i;
  227.     struct IOAudio *msg_;
  228.     
  229.     if(doneInit){
  230.        for(i=0; i<4; i++){
  231.         flushIO.ioa_Request.io_Flags = IOF_QUICK;
  232.         flushIO.ioa_Request.io_Command = ADCMD_FINISH;
  233.         flushIO.ioa_AllocKey = sIOarray_[i]->ioa_AllocKey;
  234.         flushIO.ioa_Request.io_Unit = sIOarray_[i]->ioa_Request.io_Unit;
  235.         DoIO(&flushIO);
  236.         finishIO.ioa_Request.io_Flags = IOF_QUICK;
  237.         finishIO.ioa_Request.io_Command = ADCMD_FINISH;
  238.         finishIO.ioa_AllocKey = sIOarray_[i]->ioa_AllocKey;
  239.         finishIO.ioa_Request.io_Unit = sIOarray_[i]->ioa_Request.io_Unit;
  240.         DoIO(&finishIO);
  241.         ctlIO.ioa_Request.io_Command = ADCMD_FREE;
  242.         ctlIO.ioa_Request.io_Flags = IOF_QUICK;
  243.         ctlIO.ioa_Data = NULL;
  244.         ctlIO.ioa_Length = 0;
  245.         ctlIO.ioa_AllocKey = sIOarray_[i]->ioa_AllocKey;
  246.         ctlIO.ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
  247.         ctlIO.ioa_Request.io_Unit = sIOarray_[i]->ioa_Request.io_Unit;
  248.         DoIO(&ctlIO);
  249.         while(msg_=GetMsg(sIOarray_[i]->ioa_Request.io_Message.mn_ReplyPort)){
  250.         }
  251.        }
  252.     }
  253.     if(finOpened){
  254.         CloseDevice(&finishIO);
  255.     }
  256.     if(timOpened){
  257.         CloseDevice(&timReq);
  258.     }
  259.     if(timPort_){
  260.         DeletePort(timPort_);
  261.     }
  262.     if(port5_){
  263.         DeletePort(port5_);
  264.     }
  265.     if(port6_){
  266.         DeletePort(port6_);
  267.     }
  268.     if(port7_){
  269.         DeletePort(port7_);
  270.     }
  271.     if(port8_){
  272.         DeletePort(port8_);
  273.     }
  274.     if(port9_){
  275.         DeletePort(port9_);
  276.     }
  277.     if(port10_){
  278.         DeletePort(port10_);
  279.     }
  280.     if(port11_){
  281.         DeletePort(port11_);
  282.     }
  283.     return(0);
  284. }
  285.  
  286.  
  287.  
  288. /*
  289. ---------------------------------------------------------------------------
  290.             audio_delay
  291. ---------------------------------------------------------------------------
  292.     Delays for a given amount of time.  (Used for the time between
  293.     notes.)
  294.     Receives:
  295.      int hsecs    -length of time to delay in hundredths of a sec
  296.     Returns:
  297.      <nothing>
  298. ===========================================================================
  299. */
  300. audio_delay(hsecs)
  301. int hsecs;
  302. {
  303.     timReq.tr_time.tv_secs  = (int)(hsecs/100);
  304.     timReq.tr_time.tv_micro = (int)(hsecs%100) * 10000;
  305.     DoIO(&timReq);
  306.     return(0);
  307. }
  308.  
  309.  
  310.  
  311. /*
  312. ---------------------------------------------------------------------------
  313.             EmptyPorts
  314. ---------------------------------------------------------------------------
  315.     Used internaly by th audio routines.  Waits for each pending
  316.     audio request and frees the request when it finishes.
  317.     Receives:
  318.      <nothing>
  319.     Returns:
  320.      <nothing>
  321. ===========================================================================
  322. */
  323. EmptyPorts()
  324. {
  325.     struct IOAudio *GetMsg();
  326.     struct IOAudio *msg_;
  327.     int i;
  328.     
  329.     for(i=0; i<4; i++){
  330.         if(inUse[i]){
  331.             while(msg_=GetMsg(sIOarray_[i]->ioa_Request.io_Message.mn_ReplyPort)){
  332.                 inUse[i] = 0;
  333.             }
  334.             if(!inUse[i]){
  335.                 ctlIO.ioa_Request.io_Command = ADCMD_FREE;
  336.                 ctlIO.ioa_Request.io_Flags = IOF_QUICK;
  337.                 ctlIO.ioa_Data = NULL;
  338.                 ctlIO.ioa_Length = 0;
  339.                 ctlIO.ioa_AllocKey = sIOarray_[i]->ioa_AllocKey;
  340.                 ctlIO.ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
  341.                 ctlIO.ioa_Request.io_Unit = sIOarray_[i]->ioa_Request.io_Unit;
  342.                 DoIO(&ctlIO);
  343.             }
  344.         }
  345.     }
  346.     return(0);
  347. }
  348.  
  349.     
  350.  
  351. /*
  352. ---------------------------------------------------------------------------
  353.             GetChannel
  354. ---------------------------------------------------------------------------
  355.     Finds a free channel, or if they're all busy, cancels the
  356.     oldest one and frees it.
  357.     Receives:
  358.      int *u_    -pointer to space for the unit
  359.      int *k_    -pointer to space for the key
  360.     Returns:
  361.      int *u_    -the free channel's unit
  362.      int *k_    -the free channel's key
  363. ===========================================================================
  364. */
  365. GetChannel(u_,k_)
  366. int *u_;
  367. int *k_;
  368. {
  369.     int ch;
  370.     
  371.     while(1){
  372.         EmptyPorts();
  373.         ctlIO.ioa_Request.io_Command = ADCMD_ALLOCATE;
  374.         ctlIO.ioa_Request.io_Flags = ADIOF_NOWAIT | IOF_QUICK;
  375.         ctlIO.ioa_Data = allocMap;
  376.         ctlIO.ioa_AllocKey = 0;
  377.         ctlIO.ioa_Request.io_Unit = NULL;
  378.         ctlIO.ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
  379.         ctlIO.ioa_Length = sizeof(allocMap);
  380.         BeginIO(&ctlIO);
  381.         if(!WaitIO(&ctlIO)){
  382.             *u_ = (int)(ctlIO.ioa_Request.io_Unit);
  383.             *k_ = (int)(ctlIO.ioa_AllocKey);
  384.             break;
  385.         }
  386.     }
  387.     while(1){
  388.         for(ch=0; ch<4; ch++){
  389.             if(!inUse[ch]){
  390.                 inUse[ch] = 1;
  391.                 nextTry = (ch+1)%4;
  392.                 return(ch);
  393.             }
  394.         }
  395.         EmptyPorts();
  396.     }
  397. }
  398.  
  399.  
  400.  
  401. /*
  402. ---------------------------------------------------------------------------
  403.             audio_free
  404. ---------------------------------------------------------------------------
  405.     Frees all of the channels.
  406.     Receives:
  407.      <nothing>
  408.     Returns:
  409.      <nothing>
  410. ===========================================================================
  411. */
  412. audio_free()
  413. {
  414.     while(inUse[0]+inUse[1]+inUse[2]+inUse[3]){
  415.         EmptyPorts();
  416.     }
  417.     return(0);
  418. }
  419.